package com.hangxiang.approval.service.impl;

import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.hangxiang.approval.common.*;
import com.hangxiang.approval.dao.*;
import com.hangxiang.approval.entity.*;
import com.hangxiang.approval.enums.ApplyStateEnum;
import com.hangxiang.approval.enums.ApproveStateEnum;
import com.hangxiang.approval.enums.ResultStatusEnum;
import com.hangxiang.approval.exception.MyException;
import com.hangxiang.approval.service.ApplyPeopleService;
import com.hangxiang.approval.service.ApplyService;
import com.hangxiang.approval.utils.BeanConvertUtils;
import com.hangxiang.approval.vo.ApplyInfoVo;
import com.hangxiang.approval.vo.ApplyVo;
import com.hangxiang.approval.vo.ApproveVo;
import com.hangxiang.approval.vo.PeopleVo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;


/**
 * 申请表(Apply)表服务实现类
 *
 * @author makejava
 * @since 2020-11-23 18:05:08
 */
@Service("applyService")
public class ApplyServiceImpl extends ServiceImpl<ApplyDao, Apply> implements ApplyService {
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    @Resource
    private ApplyDao applyDao;

    @Resource
    private ApproveDao approveDao;

    @Resource
    private ApplyPeopleDao applyPeopleDao;

    @Resource
    private ReviewerDao reviewerDao;

    @Resource
    private CcPersonDao ccPersonDao;

    @Resource
    private ApplyPeopleService applyPeopleService;


    /**
     * 通过ID查询单条数据
     *
     * @param common 主键
     * @return 实例对象
     */
    @Override
    public ApplyVo queryById(IntegerCommon common) {
        ApplyVo vo = new ApplyVo();
        Apply apply = applyDao.selectById(common.getValue());
        BeanUtils.copyProperties(apply, vo);
        return vo;
    }


    /**
     * 新增数据
     *
     * @param applyInsertCommon 实例对象
     * @return 实例对象
     */
    @Override
    @Transactional
    public Integer insertApply(ApplyInsertCommon applyInsertCommon) {
        // 获取审批人
        List<Reviewer> reviewers = reviewerDao.selectList(new QueryWrapper<Reviewer>()
                .lambda()
                .eq(Reviewer::getActionGroupId, applyInsertCommon.getFlowId())
                .eq(Reviewer::getIsDeleted, 0));
        if (reviewers == null || reviewers.size() == 0) {
            throw new MyException(ResultStatusEnum.DATA_ERR);
        }
        List<Integer> collect = reviewers.stream().map(Reviewer::getId).collect(Collectors.toList());
        List<CcPerson> ccPeople = ccPersonDao.selectList(new QueryWrapper<CcPerson>().lambda().eq(CcPerson::getIsDeleted, 0).in(CcPerson::getReviewerId, collect));
        Apply apply = new Apply();
        BeanUtils.copyProperties(applyInsertCommon, apply);
        apply.setApplyCode("AP" + applyInsertCommon.getUserId() + DateUtil.format(new Date(), "yyyyMMddHHmmss"));
        applyDao.insert(apply);
        Boolean b = true;
        List<ApplyPeople> applyPeoples = new ArrayList<>();
        // 获取审批人对应的抄送人
        for (Reviewer reviewer : reviewers) {
            Approve approve = new Approve();
            approve.setApplyId(apply.getId());
            approve.setUserId(reviewer.getReviewerUser());
            approve.setUserName(reviewer.getReviewerName());
            if (b) {
                approve.setState(ApproveStateEnum.EXAMINATION.getType());
            }
            approveDao.insert(approve);
            // 添加抄送人
            if (ccPeople != null || ccPeople.size() > 0) {
                List<CcPerson> collect1 = ccPeople.stream().filter(c -> c.getReviewerId().equals(reviewer.getId())).collect(Collectors.toList());
                for (CcPerson ccPerson : collect1) {
                    ApplyPeople applyPeople = new ApplyPeople();
                    applyPeople.setUserId(ccPerson.getCcPersonId());
                    applyPeople.setUserName(ccPerson.getCcPersonName());
                    applyPeople.setApplyId(apply.getId());
                    applyPeople.setApproveId(approve.getId());
                    if (b) {
                        applyPeople.setState(1);
                    }
                    applyPeoples.add(applyPeople);
                }
            }
            b = false;
        }
        applyPeopleService.saveBatch(applyPeoples);
        return apply.getId();
    }

    /**
     * 修改数据
     *
     * @param applyUpdateCommon 实例对象
     * @return 实例对象
     */
    @Override
    @Transactional
    public Integer updateApply(ApplyUpdateCommon applyUpdateCommon) {
        Apply apply = new Apply();
        BeanUtils.copyProperties(applyUpdateCommon, apply);
        applyDao.updateById(apply);
        return apply.getId();
    }

    @Override
    public PageInfo findAll(PageApplyCommon common) {
        QueryWrapper<Apply> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(Apply::getIsDeleted, 0);
        if (common.getUserId() != null) {
            queryWrapper.lambda().eq(Apply::getUserId, common.getUserId());
        }
        if (common.getApplyCode() != null) {
            queryWrapper.lambda().like(Apply::getApplyCode, common.getApplyCode());
        }
        if (common.getStartTime() != null) {
            queryWrapper.lambda().ge(Apply::getCreateTime, common.getStartTime());
        }
        if (common.getEndTime() != null) {
            queryWrapper.lambda().le(Apply::getCreateTime, common.getEndTime());
        }
        if (common.getTemplateId() != null) {
            queryWrapper.lambda().eq(Apply::getTemplateId, common.getTemplateId());
        }
        if (common.getTemplateType() != null) {
            queryWrapper.lambda().eq(Apply::getTemplateType, common.getTemplateType());
        }
        if (common.getUserName() != null) {
            queryWrapper.lambda().like(Apply::getUserName, common.getUserName());
        }
        if (common.getTempName() != null) {
            queryWrapper.lambda().like(Apply::getTempName, common.getTempName());
        }
        if (common.getState() != null) {
            queryWrapper.lambda().like(Apply::getState, common.getState());
        }
        queryWrapper.orderByDesc("update_time");
        PageHelper.startPage(common.getPageRow(), common.getPageSize());
        List<Apply> applies = applyDao.selectList(queryWrapper);
        PageInfo info = new PageInfo(applies);
        return info;
    }

    @Override
    public ApplyInfoVo findApplyInfo(IntegerCommon common) {
        ApplyInfoVo vo = new ApplyInfoVo();
        Apply apply = applyDao.selectById(common.getValue());
        BeanUtils.copyProperties(apply, vo);
        List<Approve> approves = approveDao.selectList(new QueryWrapper<Approve>()
                .lambda()
                .eq(Approve::getApplyId, apply.getId()));
        if (approves == null || approves.size() == 0) {
            throw new MyException(ResultStatusEnum.DATA_ERR);
        }
        List<Integer> collect = approves.stream().map(Approve::getId).collect(Collectors.toList());
        List<ApplyPeople> applyPeople = applyPeopleDao.selectList(new QueryWrapper<ApplyPeople>().lambda().in(ApplyPeople::getApproveId, collect));
        if (applyPeople == null || applyPeople.size() == 0) {
            throw new MyException(ResultStatusEnum.DATA_ERR);
        }
        List<ApproveVo> approveVoList = new ArrayList<>();
        for (Approve approve : approves) {
            ApproveVo approveVo = new ApproveVo();
            BeanUtils.copyProperties(approve, approveVo);
            List<ApplyPeople> collect1 = applyPeople.stream().filter(applyPeople1 -> applyPeople1.getApproveId().equals(approve.getId())).collect(Collectors.toList());
            if (collect1 != null && collect1.size() > 0) {
                List<PeopleVo> peopleVos = BeanConvertUtils.convertListTo(collect1, PeopleVo::new);
                approveVo.setList(peopleVos);
            }
            approveVoList.add(approveVo);
        }
        vo.setApproveVoList(approveVoList);
        return vo;
    }

    @Override
    @Transactional
    public void examineApply(ExamineApplyCommon common) {
        Apply apply = applyDao.selectById(common.getApplyId());
        if (apply.getState().equals(ApplyStateEnum.REJECT.getType())
                || apply.getState().equals(ApplyStateEnum.APPROVE.getType())) {
            throw new MyException(ResultStatusEnum.APPLY_STATE);
        }
        if (apply.getState().equals(ApplyStateEnum.CONFIRMED)) {
            apply.setState(ApplyStateEnum.EXAMINATION.getType());

        }
        apply.setUpdateTime(new Date());
        List<Integer> integers = new ArrayList<>();
        integers.add(ApproveStateEnum.EXAMINATION.getType());
        integers.add(ApproveStateEnum.CONFIRMED.getType());
        List<Approve> approves = approveDao.selectList(new QueryWrapper<Approve>().lambda().in(Approve::getState, integers).eq(Approve::getApplyId, common.getApplyId()));
        if (approves == null || approves.size() == 0) {
            throw new MyException(ResultStatusEnum.DATA_ERR);
        }

        List<Approve> collect = approves.stream().sorted(Comparator.comparing(Approve::getId)).collect(Collectors.toList());
        Approve approve = collect.stream().filter(approve1 -> approve1.getUserId().equals(common.getUserId()) && approve1.getState().equals(ApproveStateEnum.EXAMINATION.getType())).findAny().orElse(null);
        if (approve == null) {
            throw new MyException(ResultStatusEnum.DATA_ERR);
        }
        approve.setState(common.getState());
        // 如果驳回申请，则直接关闭
        if (common.getState().equals(ApproveStateEnum.REJECT.getType())) {
            apply.setState(ApplyStateEnum.REJECT.getType());
            // 修改抄送人状态
            updateApplyPeople(approve.getId());
            approveDao.updateById(approve);
            applyDao.updateById(apply);
            return;
        }
        // 如果没有后续审批人，则关闭当前申请
        if (collect.size() == 1) {
            if (common.getState().equals(ApproveStateEnum.REJECT.getType())) {
                apply.setState(ApplyStateEnum.REJECT.getType());
            }
            if (common.getState().equals(ApproveStateEnum.APPROVE.getType())) {
                apply.setState(ApplyStateEnum.APPROVE.getType());
            }

            updateApplyPeople(approve.getId());
            approveDao.updateById(approve);
            applyDao.updateById(apply);
            return;
        }
        // 当前申请同意，并且有后续审批人
        approve.setState(ApproveStateEnum.APPROVE.getType());
        updateApplyPeople(approve.getId());
        approveDao.updateById(approve);
        Approve approve1 = collect.get(1);
        approve1.setState(ApproveStateEnum.EXAMINATION.getType());
        updateApplyPeople(approve1.getId());
        approveDao.updateById(approve1);
        applyDao.updateById(apply);

    }


    public PageInfo examineList(ExamineListPageCommon common) {
        List<Integer> list = new ArrayList<>();
        list.add(ApproveStateEnum.REJECT.getType());
        list.add(ApproveStateEnum.APPROVE.getType());
        list.add(ApproveStateEnum.EXAMINATION.getType());
        QueryWrapper<Approve> eq = new QueryWrapper();
        eq.lambda().eq(Approve::getUserId, common.getUserId()).in(Approve::getState, list);
        List<Approve> approves = approveDao.selectList(eq);
        if (approves == null || approves.size() == 0) {
            return new PageInfo();
        }
        Set<Integer> collect = approves.stream().map(Approve::getApplyId).collect(Collectors.toSet());
        QueryWrapper<Apply> queryWrapper = new QueryWrapper();
        queryWrapper.lambda().in(Apply::getId, collect);
        if (common.getTypeId() != null){
            queryWrapper.lambda().ge(Apply::getTemplateType,common.getTypeId());
        }
        if (common.getStartTime() != null ){
            queryWrapper.lambda().ge(Apply::getCreateTime,common.getStartTime());
        }
        if (common.getEndTime() != null ){
            queryWrapper.lambda().le(Apply::getCreateTime,common.getEndTime());
        }
        queryWrapper.orderByDesc("update_time");
        PageHelper.startPage(common.getPageRow(), common.getPageSize());
        List<Apply> applies = applyDao.selectList(queryWrapper);
        PageInfo<Apply> pageInfo = new PageInfo<>(applies);
        return pageInfo;



    }

    public PageInfo duplicateList(ExamineListPageCommon common) {
        QueryWrapper<ApplyPeople> eq = new QueryWrapper();
        eq.lambda().eq(ApplyPeople::getUserId, common.getUserId()).eq(ApplyPeople::getState, 1);
        List<ApplyPeople> approves = applyPeopleDao.selectList(eq);
        if (approves == null || approves.size() == 0) {
            return new PageInfo();
        }
        Set<Integer> collect = approves.stream().map(ApplyPeople::getApplyId).collect(Collectors.toSet());
        QueryWrapper<Apply> queryWrapper = new QueryWrapper();
        queryWrapper.lambda().in(Apply::getId, collect);
        if (common.getTypeId() != null){
            queryWrapper.lambda().ge(Apply::getTemplateType,common.getTypeId());
        }
        queryWrapper.orderByDesc("update_time");
        PageHelper.startPage(common.getPageRow(), common.getPageSize());
        List<Apply> applies = applyDao.selectList(queryWrapper);
        PageInfo<Apply> pageInfo = new PageInfo<>(applies);
        return pageInfo;
    }


    // 审批修改抄送人状态
    public void updateApplyPeople(Integer approve) {
        ApplyPeople applyPeople = new ApplyPeople();
        applyPeople.setState(1);
        applyPeopleDao.update(applyPeople, new QueryWrapper<ApplyPeople>().lambda().eq(ApplyPeople::getApproveId, approve));
    }


}